﻿using FPSO.HMI.Views.Dialog;
using FPSO.Models.Constant;
using FPSO.Models.Domain;
using FPSO.Services;
using FPSO.Services.Impl;
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using Opc.Ua;
using System.Xml;
using FPSO.HMI.Utils;
using System.Management.Instrumentation;
using OpcUaHelper;
using FPSO.HMI.Controls;
using Prism.Services.Dialogs;
using static FPSO.Models.Constant.TankConstant;
using SafeLoad.NControl;
using System.Xml.Linq;
using System.Threading;

namespace FPSO.HMI.Views
{
    /// <summary>
    /// ExecuteView.xaml 的交互逻辑
    /// </summary>
    public partial class ExecuteView : UserControl
    {
        private DispatcherTimer taskTimer;
        private DispatcherTimer updateTaskQueueTimer;

		//simuTaskTimer为临时下发任务的计时器，用于监控任务状态
		//为防止下发任务始终没有达到目标值，计时器无法停止，设置任务执行时间
		private DispatcherTimer simuTaskTimer = null;
		private int simuTaskTick = 0;
		private int maxSimuTaskTick = 180;
		private int simuTaskTimeSpan = 20;

        private DateTime startTime;
        private TaskTankCalcService taskTankCalcService = null;
        private string[] dataFiles = null;
        public ExecuteView()
        {
            InitializeComponent();
            // 去除监控图
            //curveLine.SetCurve("剪力", null, Colors.DodgerBlue);
            //curveLine.SetCurve("弯矩", null, Colors.DarkOrange);

            startTime = DateTime.MinValue;
            taskQueue.TaskService = new DBTankTaskService();
            taskTankCalcService = new TaskTankCalcService(taskQueue.TaskService);

            taskTimer = new DispatcherTimer();
            taskTimer.Interval = TimeSpan.FromSeconds(1);
            taskTimer.Tick += TaskTimer_Tick;
            taskTimer.Start();

			//DEBUG 暂时封掉
            //updateTaskQueueTimer = new DispatcherTimer();
            //updateTaskQueueTimer.Interval = TimeSpan.FromMilliseconds(600000);
            //updateTaskQueueTimer.Tick += TaskQueueTimer_Tick;
            //updateTaskQueueTimer.Start();

            // 缓存真实数据获取列表
            //dataFiles = getDataFiles();
        }
        /// <summary>
        /// 获取真实数据获取列表
        /// </summary>
        /// <returns></returns>
        static string[] getDataFiles()
        {
            try
            {
                return Directory.GetFiles("D:\\SAFELOAD\\PROJ_708海工自研_FPSO智能液货集成控制系统_20210310\\20231113_数据备份_20231106-1111\\智能装配载数据备份\\Datalog", "log_*");
            }
            catch (Exception)
            {
                return Directory.GetFiles("D:\\DevEnv\\fpso_exe\\Datalog", "log_*");
            }
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            if (!oilBallast.IsInit())
            {
                oilBallast.StartReal();
            }
            if (!otherTanksBarlist.IsInitBindingService())
            {
                otherTanksBarlist.StartReal();
            }
        }

        public void ReloadTaskQueue()
        {
            taskQueue.ControlUpdate();
        }

        private void TaskQueueTimer_Tick(object sender, EventArgs e)
        {
            Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
            taskQueue.ControlUpdateByRate(currentVolmDic0);
        }

        private void TaskTimer_Tick(object sender, EventArgs e)
        {
            //待测试
            oilBallast.SetImitateTime(DateTime.Now);

            //DEBUG 暂时封掉右下角其他液舱的数据
            otherTanksBarlist.ReflushUIValues(DateTime.Now);

            taskQueue.CurrentTime = DateTime.Now;
        }

        private void oilBallast_OnAddTankTask(string srcTankId)
        {
			TankLoadTypeSelectDialog tankLoadTypeSelectDialog = new TankLoadTypeSelectDialog();
			if(tankLoadTypeSelectDialog.ShowDialog() == true)
			{
				if(tankLoadTypeSelectDialog.LoadTypeSelect == 1)
				{
					//DEBUG 这里仿照压载倒舱，点击可制定货油注入任务，原先制定计划的过程暂时封掉
					Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
					COTLoadTaskDialog loadTaskDialog = new COTLoadTaskDialog(srcTankId, currentVolmDic0, false);
					if (loadTaskDialog.ShowDialog() == true)
					{
						List<ConstantTankInfo> taskInfos = TankConstant.getCOTTank();
						Dictionary<string, double> taskTankVolume = currentVolmDic0;
						string tar_tankName = loadTaskDialog.g_TargetTank;
						double adjustvol = loadTaskDialog.g_Adjustvol;
						Int16 srctankno = 0;
						for (int i = 0; i < taskInfos.Count; i++)
						{
							ConstantTankInfo info = taskInfos[i];
							string tankname = info.TankName;
							if (tankname == srcTankId)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] += adjustvol;
								srctankno = Convert.ToInt16(i + 1);
								break;
							}
						}
						SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
						ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
						if (calcResult.GetShipCheckStatus() == true)
						{
							//再次确认
							var dialgoResult = MessageBox.Show("完成货油注入任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
							if (dialgoResult == MessageBoxResult.Yes)
							{
								double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
								Int16 readflag = 2;
								Int16 tanktype = 0;
								Int16 taskop = 1;

								string taskpre = "Task1CTInstructCache[0]";
								string tag0 = "ReadFlag";
								string tag1 = "sourceTkNo";
								string tag2 = "targetTkNo";
								string tag3 = "TkType";
								string tag4 = "TargetLevel";
								string tag5 = "TaskOp";
								string tag6 = "TargetLevelIdx";

								string tag_start = "HmiTask1CTInstructStartCmd";
								string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
								string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
								string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
								string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
								string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
								string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
								string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
								string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								//注入没有原舱，代码以0代替
								App.UaClient.WriteNode<Int16>(status_tag1, 0);
								App.UaClient.WriteNode<Int16>(status_tag2, srctankno);
								App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
								App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));

								//[实船调试] 在下面一句设断点，逐步调试，看能否正确发出数据
								App.UaClient.WriteNode<Int16>(status_tag5, taskop);
								Int16 targetLevelIdx = TankConstant.g_TargetCotLevelIdx[srctankno - 1];
								App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

								dialgoResult = MessageBox.Show("完成货油注入任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
								if (dialgoResult == MessageBoxResult.Yes)
								{
									App.UaClient.WriteNode<Int16>(status_tag0, readflag);
									App.UaClient.WriteNode<Boolean>(status_tag_start, true);

									string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M", srcTankId, srctanklevel);
									CommUtil.AddSystemLog(6, 0, info);
									simuTaskTimer = new DispatcherTimer();
									simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
									simuTaskTimer.Tick += SimuTaskTimer_Tick1;
									simuTaskTimer.Tag = string.Format("{0}:{1:N3}", srcTankId, srctanklevel);
									simuTaskTick = 0;
									simuTaskTimer.Start();
								}
							}
						}
					}
				}
				else if(tankLoadTypeSelectDialog.LoadTypeSelect == 2)
				{
					//DEBUG 双击主界面设置舱室调载目标的交互暂时封掉
					Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
					Dictionary<string, double> currentLevelDic0 = oilBallast.GetTankInnDic();
					WBTSwapTaskDialog wBTSwapTaskDialog = new WBTSwapTaskDialog(srcTankId, currentVolmDic0, currentLevelDic0, false);
					if (wBTSwapTaskDialog.ShowDialog() == true)
					{
						List<ConstantTankInfo> taskInfos = TankConstant.getCOTTank();
						Dictionary<string, double> taskTankVolume = currentVolmDic0;
						string tar_tankName = wBTSwapTaskDialog.g_TargetTank;
						double adjustvol = wBTSwapTaskDialog.g_Adjustvol;
						bool heelChecked = wBTSwapTaskDialog.g_HeelChecked;
						Int16 srctankno = 0;
						Int16 tartankno = 0;
						for (int i = 0; i < taskInfos.Count; i++)
						{
							ConstantTankInfo info = taskInfos[i];
							string tankname = info.TankName;
							if (tankname == srcTankId)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] -= adjustvol;
								srctankno = Convert.ToInt16(i + 1);
							}
							else if (tankname == tar_tankName)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] += adjustvol;
								tartankno = Convert.ToInt16(i + 1);
							}
						}

						SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
						ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
						if (calcResult.GetShipCheckStatus() == true)
						{
							//再次确认
							var dialgoResult = MessageBox.Show("完成倒舱任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
							if (dialgoResult == MessageBoxResult.Yes)
							{
								double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
								double tartanklevel = calcResult.GetTankCalcStateByName(tar_tankName).Inn;
								Int16 readflag = 2;
								Int16 tanktype = 0;
								Int16 taskop = 3;

								string taskpre = "Task3CTInstructCache[0]";
								string tag0 = "ReadFlag";
								string tag1 = "sourceTkNo";
								string tag2 = "targetTkNo";
								string tag3 = "TkType";
								string tag4 = "TargetLevel";
								string tag5 = "TaskOp";
								string tag6 = "TargetLevelIdx";

								string tag_start = "HmiTask3CTInstructStartCmd";
								string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
								string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
								string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
								string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
								string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
								string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
								string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
								string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
								App.UaClient.WriteNode<Int16>(status_tag2, tartankno);
								App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
								App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(tartanklevel));
								App.UaClient.WriteNode<Int16>(status_tag5, taskop);
								Int16 targetLevelIdx = TankConstant.g_TargetCotLevelIdx[srctankno - 1];
								App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

								dialgoResult = MessageBox.Show("完成倒舱任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
								if (dialgoResult == MessageBoxResult.Yes)
								{
									App.UaClient.WriteNode<Int16>(status_tag0, readflag);
									App.UaClient.WriteNode<Boolean>(status_tag_start, true);

									simuTaskTimer = new DispatcherTimer();
									simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
									simuTaskTimer.Tick += SimuTaskTimer_Tick1;
									if (heelChecked)
									{
										ShipDraught realDraught = shipInfo.GetRealShipInfo();
										double Dm_ps = realDraught.MidPDraft;
										double Dm_sb = realDraught.MidSDraft;
										string info = string.Format("装载舱室：[{0}] 当前液位[{1:N3}]M，当前舯左吃水[{2:N3}]M，当前舯右吃水[{3:N3}]M",
											tar_tankName, tartanklevel, Dm_ps, Dm_sb);
										CommUtil.AddSystemLog(6, 1, info);
										simuTaskTimer.Tag = string.Format("Draft:{0}:{1:N3}", tar_tankName, tartanklevel);
									}
									else
									{
										string info = string.Format("排载舱室：[{0}] 目标液位[{1:N3}]M，压载舱室：[{2}] 目标液位[{3:N3}]M",
										srcTankId, srctanklevel, tar_tankName, tartanklevel);
										CommUtil.AddSystemLog(6, 0, info);
										simuTaskTimer.Tag = string.Format("{0}:{1:N3}", tar_tankName, tartanklevel);
									}
									simuTaskTick = 0;
									simuTaskTimer.Start();
									return;
								}
							}
						}
					}
				}
			}
		}

		private void oilBallast_OnAddBwtTankTask(string srcTankId)
		{
			TankLoadTypeSelectDialog tankLoadTypeSelectDialog = new TankLoadTypeSelectDialog();
			if (tankLoadTypeSelectDialog.ShowDialog() == true)
			{
				if (tankLoadTypeSelectDialog.LoadTypeSelect == 2)
				{
					//DEBUG 双击主界面设置舱室调载目标的交互暂时封掉
					Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
					Dictionary<string, double> currentLevelDic0 = oilBallast.GetTankInnDic();
					WBTSwapTaskDialog wBTSwapTaskDialog = new WBTSwapTaskDialog(srcTankId, currentVolmDic0, currentLevelDic0, true);
					if (wBTSwapTaskDialog.ShowDialog() == true)
					{
						List<ConstantTankInfo> taskInfos = TankConstant.getWBTTank();
						Dictionary<string, double> taskTankVolume = currentVolmDic0;
						string tar_tankName = wBTSwapTaskDialog.g_TargetTank;
						double adjustvol = wBTSwapTaskDialog.g_Adjustvol;
						bool heelChecked = wBTSwapTaskDialog.g_HeelChecked;
						Int16 srctankno = 0;
						Int16 tartankno = 0;
						for (int i = 0; i < taskInfos.Count; i++)
						{
							ConstantTankInfo info = taskInfos[i];
							string tankname = info.TankName;
							if (tankname == srcTankId)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] -= adjustvol;
								srctankno = Convert.ToInt16(i + 1);
							}
							else if (tankname == tar_tankName)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] += adjustvol;
								tartankno = Convert.ToInt16(i + 1);
							}
						}

						SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
						ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
						if (calcResult.GetShipCheckStatus() == true)
						{
							//再次确认
							var dialgoResult = MessageBox.Show("完成倒舱任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
							if (dialgoResult == MessageBoxResult.Yes)
							{
								double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
								double tartanklevel = calcResult.GetTankCalcStateByName(tar_tankName).Inn;
								Int16 readflag = 2;
								Int16 tanktype = 1;
								Int16 taskop = 3;

								string taskpre = "Task3BTInstructCache[0]";
								string tag0 = "ReadFlag";
								string tag1 = "sourceTkNo";
								string tag2 = "targetTkNo";
								string tag3 = "TkType";
								string tag4 = "TargetLevel";
								string tag5 = "TaskOp";
								string tag6 = "TargetLevelIdx";

								string tag_start = "HmiTask3BTInstructStartCmd";
								string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
								string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
								string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
								string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
								string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
								string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
								string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
								string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
								App.UaClient.WriteNode<Int16>(status_tag2, tartankno);
								App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
								App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(tartanklevel));
								App.UaClient.WriteNode<Int16>(status_tag5, taskop);
								Int16 targetLevelIdx = TankConstant.g_TargetBwtLevelIdx[srctankno - 1];
								App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

								dialgoResult = MessageBox.Show("完成倒舱任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
								if (dialgoResult == MessageBoxResult.Yes)
								{
									App.UaClient.WriteNode<Int16>(status_tag0, readflag);
									App.UaClient.WriteNode<Boolean>(status_tag_start, true);

									simuTaskTimer = new DispatcherTimer();
									simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
									simuTaskTimer.Tick += SimuTaskTimer_Tick1;
									if (heelChecked)
									{
										ShipDraught realDraught = shipInfo.GetRealShipInfo();
										double Dm_ps = realDraught.MidPDraft;
										double Dm_sb = realDraught.MidSDraft;
										string info = string.Format("装载舱室：[{0}] 当前液位[{1:N3}]M，当前舯左吃水[{2:N3}]M，当前舯右吃水[{3:N3}]M",
											tar_tankName, tartanklevel, Dm_ps, Dm_sb);
										CommUtil.AddSystemLog(6, 1, info);
										simuTaskTimer.Tag = string.Format("Draft:{0}:{1:N3}", tar_tankName, tartanklevel);
									}
									else
									{
										string info = string.Format("排载舱室：[{0}] 目标液位[{1:N3}]M，压载舱室：[{2}] 目标液位[{3:N3}]M",
										srcTankId, srctanklevel, tar_tankName, tartanklevel);
										CommUtil.AddSystemLog(6, 0, info);
										simuTaskTimer.Tag = string.Format("{0}:{1:N3}", tar_tankName, tartanklevel);
									}
									simuTaskTick = 0;
									simuTaskTimer.Start();
									return;
								}
							}
						}
					}
				}
				else if (tankLoadTypeSelectDialog.LoadTypeSelect == 1)
				{
					//DEBUG 这里仿照压载倒舱，点击可制定货油注入任务，原先制定计划的过程暂时封掉
					Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
					COTLoadTaskDialog loadTaskDialog = new COTLoadTaskDialog(srcTankId, currentVolmDic0, true);
					if (loadTaskDialog.ShowDialog() == true)
					{
						List<ConstantTankInfo> taskInfos = TankConstant.getWBTTank();
						Dictionary<string, double> taskTankVolume = currentVolmDic0;
						string tar_tankName = loadTaskDialog.g_TargetTank;
						double adjustvol = loadTaskDialog.g_Adjustvol;
						int loadType = loadTaskDialog.g_LoadType;
						if (loadType == 2)
							adjustvol = -adjustvol;
						Int16 srctankno = 0;
						for (int i = 0; i < taskInfos.Count; i++)
						{
							ConstantTankInfo info = taskInfos[i];
							string tankname = info.TankName;
							if (tankname == srcTankId)
							{
								string tankId = info.TankID;
								taskTankVolume[tankId] += adjustvol;
								srctankno = Convert.ToInt16(i + 1);
								break;
							}
						}
						SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
						ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
						if (calcResult.GetShipCheckStatus() == true)
						{
							//再次确认
							var dialgoResult = MessageBox.Show("完成压载任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
							if (dialgoResult == MessageBoxResult.Yes)
							{
								double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
								Int16 readflag = 2;
								Int16 tanktype = 1;
								Int16 taskop = Convert.ToInt16(loadType);

								string taskpre = "Task1BTInstructCache[0]";
								string tag0 = "ReadFlag";
								string tag1 = "sourceTkNo";
								string tag2 = "targetTkNo";
								string tag3 = "TkType";
								string tag4 = "TargetLevel";
								string tag5 = "TaskOp";
								string tag6 = "TargetLevelIdx";

								string tag_start = "HmiTask1BTInstructStartCmd";
								string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
								string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
								string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
								string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
								string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
								string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
								string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
								string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								//注入没有原舱，代码以0代替
								//排载过程，舱室编号下发至sourceTkNo；tag1
								//压载过程，舱室编号下发至targetTkNo。tag2
								if (loadType == 2)
								{
									App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
									App.UaClient.WriteNode<Int16>(status_tag2, 0);
								}
								else
								{
									App.UaClient.WriteNode<Int16>(status_tag1, 0);
									App.UaClient.WriteNode<Int16>(status_tag2, srctankno);
								}

								App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
								//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
								App.UaClient.WriteNode<Int16>(status_tag5, taskop);

								Int16 targetLevelIdx = TankConstant.g_TargetBwtLevelIdx[srctankno - 1];
								App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

								dialgoResult = MessageBox.Show("完成压载任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
								if (dialgoResult == MessageBoxResult.Yes)
								{
									App.UaClient.WriteNode<Int16>(status_tag0, readflag);
									App.UaClient.WriteNode<Boolean>(status_tag_start, true);

									string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M", srcTankId, srctanklevel);
									CommUtil.AddSystemLog(6, 0, info);
									simuTaskTimer = new DispatcherTimer();
									simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
									simuTaskTimer.Tick += SimuTaskTimer_Tick1;
									simuTaskTimer.Tag = string.Format("{0}:{1:N3}", srcTankId, srctanklevel);
									simuTaskTick = 0;
									simuTaskTimer.Start();
								}
							}
						}
					}
				}
			}
		}
		private void SimuTaskTimer_Tick1(object sender, EventArgs e)
		{
			string tag = Convert.ToString(simuTaskTimer.Tag);
			Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
			SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
			ManualCalcResult calcResult = algorithmService.CallManualCalc(currentVolmDic0, 3);

			bool check = true;
			if (tag.Contains("DRAFT"))
			{
				string tar_tankname = tag.Split(':')[1];
				double tar_tanklevel = Convert.ToDouble(tag.Split(':')[1]);
				ShipDraught realDraught = shipInfo.GetRealShipInfo();
				double Dm_ps = realDraught.MidPDraft;
				double Dm_sb = realDraught.MidSDraft;
				string info = string.Format("装载舱室：[{0}] 当前液位[{1:N3}]M，当前舯左吃水[{2:N3}]M，当前舯右吃水[{3:N3}]M",
					tar_tankname, tar_tanklevel, Dm_ps, Dm_sb);
				CommUtil.AddSystemLog(6, 1, info);

				bool stop_check = false;
				//如果两舯吃水差小于10cm，则返回
				if (Math.Abs(Dm_ps - Dm_sb) < 0.1)
				{
					check = false;
					stop_check = true;
				}
				//很可能采集值波动较大，始终无法落在上条件区间，则通过调载方向判定
				else
				{
					//如果目标舱是左舱，则右排载左压载，原状态为右倾，至左倾时返回
					//如果目标舱是右舱，则左排载右压载，原状态为左倾，至右倾时返回
					if ((tar_tankname.Contains("P") && (Dm_ps - Dm_sb > 0.1))
						|| (tar_tankname.Contains("S") && (Dm_sb - Dm_ps > 0.1)))
					{
						check = false;
						stop_check = true;
					}
				}
				if(stop_check)
				{
					string tag_stop = "HMITaskStopCmd";
					string status_tag0 = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_stop);
					App.UaClient.WriteNode<Boolean>(status_tag0, true);
					CommUtil.AddSystemLog(6, 0, "调载完成");
					simuTaskTimer.Stop();
				}
			}
			else
			{
				string tar_tankname = tag.Split(':')[0];
				double tar_tanklevel = Convert.ToDouble(tag.Split(':')[1]);
				double cur_tanklevel = calcResult.GetTankCalcStateByName(tar_tankname).Inn;
				string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M，当前液位[{2:N3}]M",
					tar_tankname, tar_tanklevel, cur_tanklevel);
				CommUtil.AddSystemLog(6, 0, info);

				if(cur_tanklevel >= tar_tanklevel)
				{
					check = false;
					CommUtil.AddSystemLog(6, 0, "调载完成");
				}
			}
			simuTaskTick++;
			if(simuTaskTick > maxSimuTaskTick)
				check = false;

			if (!check)
			{
				//此处需要向下位机发送终止当前过程的命令
				//string tag_stop = "HMITaskStopCmd";
				//string status_tag0 = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_stop);
				//App.UaClient.WriteNode<Boolean>(status_tag0, true);
				simuTaskTimer.Stop();
			}
		}

		public void SetShipDraught(ShipDraught calcDraught, ShipDraught realDraught)
        {
            shipInfo.SetShipInfo(calcDraught, realDraught);
        }
        public void SetTankStatus(ManualCalcResult calcResult)
        {
            oilBallast.SetTankStatus(calcResult);
			otherTanksBarlist.SetTankStatus(calcResult);
		}

		//舱室监控曲线窗口
		private TankMonitorDialog tankMonitorDialogInstance;
        //实船吃水对比曲线窗口
        private RealDataMonitorDialog realDataMonitorDialogInstance;

        /// <summary>
        /// 打开舱室监控曲线图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TankMonitorButton_Click(object sender, RoutedEventArgs e)
        {
            if (tankMonitorDialogInstance == null || !tankMonitorDialogInstance.IsVisible)
            {
                tankMonitorDialogInstance = new TankMonitorDialog();
                tankMonitorDialogInstance.Closed += TankMonitorDialogClosed;
                tankMonitorDialogInstance.Show();
            }
            else
            {
                // 如果窗口已经可见，可以选择将其激活
                tankMonitorDialogInstance.Activate();
            }
        }
        private void TankMonitorDialogClosed(object sender, EventArgs e)
        {
            // 窗口关闭时，将实例设置为 null，以便可以再次创建
            tankMonitorDialogInstance = null;
        }


        /// <summary>
        /// 打开实船吃水对比曲线图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void RealDataTestButton_Click(object sender, RoutedEventArgs e)
        {
            if (realDataMonitorDialogInstance == null || !realDataMonitorDialogInstance.IsVisible)
            {
                realDataMonitorDialogInstance = new RealDataMonitorDialog();
                realDataMonitorDialogInstance.Closed += RealDataMonitorDialogClosed;
                realDataMonitorDialogInstance.Show();
            }
            else
            {
                realDataMonitorDialogInstance.Activate();
            }
        }
        private void RealDataMonitorDialogClosed(object sender, EventArgs e)
        {
            realDataMonitorDialogInstance = null;
        }

        //DEBUG 下面是制作的虚拟装卸过程
        private string[] testMsg = {
            "{AutoSeq}#{NO4_COT_S#9756.46#1.00#18.67#9756.46#0.80#-32.05#-9.18#12.12#-46.40#-17.70#0.00#NO3_WBT_P#3643.45#1.02#8.34#3554.59#0.58#2.80#14.19#2.66#-17.70#23.30#0.00#NO3_WBT_S#2635.09#1.02#3.58#2570.82#0.42#2.80#-11.99#1.50#-17.70#23.30#0.00#NO4_WBT_S#0.00#1.02#0.00#0.00#0.00#-32.05#-10.10#0.00#-46.40#-17.70#0.00#}#{88449.11#9756.46#37026.85#22.72#-0.59#13.75#8.97#9.66#0.00#-1.44#57.84#25.98#}",
            "{AutoSeq}#{NO1_COT_S#9756.46#1.00#18.67#9756.46#0.80#66.35#-9.18#12.12#52.00#80.70#8780813.28#NO1_WBT_S#0.00#1.02#0.00#0.00#0.00#66.28#-10.04#0.00#52.00#80.70#0.00#NO3_WBT_P#4040.58#1.02#10.92#3942.03#0.64#2.80#14.83#3.34#-17.70#23.30#406692.52#NO3_WBT_S#2237.96#1.02#2.46#2183.38#0.36#2.80#-11.05#1.25#-17.70#23.30#-406692.52#NO4_WBT_P#2197.49#1.02#5.55#2143.89#0.50#-32.05#13.19#1.99#-46.40#-17.70#-1929501.45#NO5_WBT_S#2195.87#1.02#5.56#2142.31#0.50#-60.73#-13.18#1.99#-75.10#-46.40#-1928078.10#}#{89422.19#19512.92#28243.47#22.48#5.68#13.77#8.71#9.77#0.00#2.22#46.27#33.67#}",
            "{AutoSeq}#{NO3_COT_P#9756.46#1.00#18.67#9756.46#0.80#-3.35#9.18#12.12#-17.70#11.00#5853875.52#NO3_WBT_P#1154.28#1.02#1.29#1126.13#0.18#2.80#10.85#0.65#-17.70#23.30#-1443440.32#NO5_WBT_S#4391.59#1.02#25.50#4284.48#1.00#-60.74#-16.93#8.64#-75.10#-46.40#0.00#}#{98235.10#29269.38#27299.93#21.54#3.39#13.95#7.59#10.67#-0.00#1.11#42.64#31.59#}",
            "{AutoSeq}#{NO5_COT_S#9756.46#1.00#18.67#9756.46#0.80#-60.75#-9.18#12.12#-75.10#-46.40#5017607.59#NO3_WBT_P#1845.73#1.02#2.04#1800.71#0.29#2.80#10.99#1.03#-17.70#23.30#-1514388.87#NO3_WBT_S#1293.54#1.02#1.44#1261.99#0.21#2.80#-10.88#0.73#-17.70#23.30#-2160851.73#NO5_WBT_S#0.00#1.02#0.00#0.00#0.00#-60.73#-10.08#0.00#-75.10#-46.40#0.00#}#{103599.97#39025.84#22908.34#21.15#0.07#14.00#7.15#11.21#0.00#-0.91#62.80#33.37#}",
            "{AutoSeq}#{NO2_COT_P#9756.46#1.00#18.67#9756.46#0.80#37.65#9.18#12.12#23.30#52.00#3902583.68#NO1_WBT_P#2195.22#1.02#5.56#2141.68#0.50#66.33#13.18#1.99#52.00#80.70#-856672.40#NO2_WBT_P#0.00#1.02#0.00#0.00#0.00#37.65#10.10#0.00#23.30#52.00#0.00#NO2_WBT_S#2197.49#1.02#5.55#2143.89#0.50#37.65#-13.19#1.99#23.30#52.00#-857556.20#NO3_WBT_P#1155.27#1.02#1.29#1127.10#0.18#2.80#10.85#0.65#-17.70#23.30#-2329206.60#NO3_WBT_S#1983.99#1.02#2.19#1935.60#0.32#2.80#-11.01#1.11#-17.70#23.30#124062.24#}#{104569.15#48782.30#14121.06#21.08#-0.19#14.00#7.08#11.30#-0.00#-1.06#65.53#37.29#}",
            "{AutoSeq}#{NO2_COT_S#9756.46#1.00#18.67#9756.46#0.80#37.65#-9.18#12.12#23.30#52.00#3512325.31#NO1_WBT_P#4390.30#1.02#25.50#4283.22#1.00#66.34#16.93#8.64#52.00#80.70#0.00#NO2_WBT_S#0.00#1.02#0.00#0.00#0.00#37.65#-10.10#0.00#23.30#52.00#0.00#NO3_WBT_P#1845.73#1.02#2.04#1800.71#0.29#2.80#10.99#1.03#-17.70#23.30#-1284789.68#NO3_WBT_S#1293.54#1.02#1.44#1261.99#0.21#2.80#-10.88#0.73#-17.70#23.30#-552830.62#}#{114323.20#58538.76#14118.64#20.34#3.59#14.09#6.25#12.31#0.00#1.72#66.48#47.37#}",
            "{AutoSeq}#{NO5_COT_P#9756.46#1.00#18.67#9756.46#0.80#-60.75#9.18#12.12#-75.10#-46.40#3193023.01#NO3_WBT_P#1154.28#1.02#1.29#1126.13#0.18#2.80#10.85#0.65#-17.70#23.30#-0.00#NO3_WBT_S#1984.98#1.02#2.19#1936.57#0.32#2.80#-11.01#1.11#-17.70#23.30#0.00#NO5_WBT_P#0.00#1.02#0.00#0.00#0.00#-60.73#10.08#0.00#-75.10#-46.40#0.00#}#{119688.07#68295.21#9727.05#20.13#0.71#14.13#6.00#12.84#0.00#-0.21#86.46#47.25#}",
            "{AutoSeq}#{NO1_COT_P#9756.46#1.00#18.67#9756.46#0.80#66.35#9.18#12.12#52.00#80.70#2701788.70#NO1_WBT_P#0.00#1.02#0.00#0.00#0.00#66.28#10.04#0.00#52.00#80.70#0.00#NO3_WBT_P#557.38#1.02#0.64#543.78#0.09#2.80#10.64#0.32#-17.70#23.30#489404.79#NO3_WBT_S#2581.89#1.02#3.40#2518.92#0.41#2.80#-11.84#1.46#-17.70#23.30#-489404.79#}#{125054.23#78051.67#5336.76#19.83#3.53#14.17#5.66#13.40#0.00#2.02#83.05#42.63#}",
            "{AutoSeq}#{NO3_COT_S#9756.46#1.00#18.67#9756.46#0.80#-3.35#-9.18#12.12#-17.70#11.00#2341550.21#NO3_WBT_P#4959.64#1.02#16.89#4838.67#0.79#2.80#15.92#5.30#-17.70#23.30#2212092.04#NO3_WBT_S#1318.71#1.02#1.47#1286.55#0.21#2.80#-10.89#0.75#-17.70#23.30#375767.48#}#{137949.77#87808.13#8475.84#19.45#3.02#13.88#5.57#14.69#-0.00#2.05#103.39#91.30#}",
            "{AutoSeq}#{NO4_COT_P#9756.46#1.00#18.67#9756.46#0.80#-32.05#9.18#12.12#-46.40#-17.70#2066073.71#NO3_WBT_P#458.47#1.02#0.53#447.29#0.07#2.80#10.60#0.26#-17.70#23.30#268371.42#NO3_WBT_S#0.00#1.02#0.00#0.00#0.00#2.80#-10.10#0.00#-17.70#23.30#0.00#NO4_WBT_P#0.00#1.02#0.00#0.00#0.00#-32.05#10.10#0.00#-46.40#-17.70#0.00#}#{139688.86#97564.59#458.47#19.45#1.14#14.32#5.12#14.84#0.00#0.55#117.65#90.99#}"
        };

        private List<OpcTask> taskList;
        private int testIndex = 0;
        private bool simu_begin = false;
        private List<string> simuTankList;
        private List<double> simuTankLevelList;
        private List<int> simuTankStatusList;
        private List<List<string>> simuTankValvesList;
        private OPCUtil opcUtil;

        private List<OpcTask> GetTaskList()
        {
            List<OpcTask> taskList = new List<OpcTask>();

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.Load("./opctask.xml");
                XmlNodeList nodeList = xml.SelectNodes("/Tasks/Task");
                foreach (XmlNode task in nodeList)
                {
                    OpcTask opcTask = new OpcTask();
                    opcTask.TaskName = task.Attributes["Name"].Value;
                    opcTask.TagList = new List<OPCTag>();
                    foreach (XmlNode tag in task.ChildNodes)
                    {
                        string opcType = tag.Attributes["OpcType"].Value.Trim().ToLower();
                        string opcValue = tag.Attributes["Value"].Value.Trim();

                        OPCTag opcTag = new OPCTag();
                        opcTag.OpcName = tag.Attributes["OPCTag"].Value.Trim();
                        opcTag.OpcType = opcType;
                        opcTag.OpcValue = new DataValue();

                        switch (opcType)
                        {
                            case "byte": opcTag.OpcValue.Value = Convert.ToByte(opcValue); break;
                            case "sbyte": opcTag.OpcValue.Value = Convert.ToSByte(opcValue); break;
                            case "short": opcTag.OpcValue.Value = Convert.ToInt16(opcValue); break;
                            case "ushort": opcTag.OpcValue.Value = Convert.ToUInt16(opcValue); break;
                            case "int": opcTag.OpcValue.Value = Convert.ToInt32(opcValue); break;
                            case "uint": opcTag.OpcValue.Value = Convert.ToUInt32(opcValue); break;
                            case "long": opcTag.OpcValue.Value = Convert.ToInt64(opcValue); break;
                            case "ulong": opcTag.OpcValue.Value = Convert.ToUInt64(opcValue); break;
                            case "real": opcTag.OpcValue.Value = Convert.ToSingle(opcValue); break;
                            case "bin":
                                {
                                    opcTag.OpcValue.Value = opcValue.PadLeft(16, '0');
                                    break;
                                }
                        }

                        opcTask.TagList.Add(opcTag);
                    }
                    taskList.Add(opcTask);
                }
            }
            catch (Exception ex)
            {
				CommUtil.AddSystemLog(7, 0, ex.Message);
            }

            return taskList;
        }

		//NOTICE
		private void SimuDataTestButton_Click(object sender, RoutedEventArgs e)
		{
			return;
			try 
			{
				OpcUaClient uaClient = App.UaClient;
				if (uaClient == null)
				{
					uaClient = new OpcUaClient();
					uaClient.ConnectServer(SysConfig.OPCConnStr, SysConfig.OPCBackupConnStr).Wait();
				}

				string taskpre = "Task1BTInstructCache[0]";
				//string taskpre = "Task1CTInstructCache[1]";
				string tag0 = "ReadFlag";
				string tag1 = "sourceTkNo";
				string tag2 = "targetTkNo";
				string tag3 = "TkType";
				string tag4 = "TargetLevel";
				string tag5 = "TaskOp";
				string tag_start = "HmiTask1BTInstructStartCmd";
				string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
				string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
				string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
				string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
				string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
				string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
				string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

				App.UaClient.WriteNode<Int16>(status_tag0, 2);
				App.UaClient.WriteNode<Int16>(status_tag1, 1);
				App.UaClient.WriteNode<Int16>(status_tag2, 2);
				App.UaClient.WriteNode<Int16>(status_tag3, 1);
				App.UaClient.WriteNode<float>(status_tag4, 3.2f);
				App.UaClient.WriteNode<Int16>(status_tag5, 2);
				App.UaClient.WriteNode<Boolean>(status_tag_start, true);
				return;
			}
			catch(Exception ex) 
			{
			}
			
		}
		private void SimuDataTestButton_Click1(object sender, RoutedEventArgs e)
        {
            simu_begin = !simu_begin;
            if (simu_begin)
            {
                opcUtil = new OPCUtil();
                testIndex = 0;
                taskList = GetTaskList();
                simuTaskTimer = new DispatcherTimer();
                simuTaskTimer.Interval = TimeSpan.FromSeconds(1);
                simuTaskTimer.Tick += SimuTaskTimer_Tick;
                simuTaskTimer.Start();
                simuTankList = new List<string>();
                simuTankLevelList = new List<double>();
                simuTankStatusList = new List<int>();
            }
            else
            {
                simuTaskTimer.Stop();
            }
        }
        private void SimuTaskTimer_Tick(object sender, EventArgs e)
        {
            bool nextIndexCheck = false;
            if (simuTankStatusList.Count() == 0)
            {
                nextIndexCheck = true;
            }
            else
            {
                nextIndexCheck = true;
                foreach (int statuscheck in simuTankStatusList)
                {
                    if (statuscheck != 0)
                    {
                        nextIndexCheck = false;
                        break;
                    }
                }
                if (nextIndexCheck)
                    testIndex++;
            }

            if (nextIndexCheck)
            {
                simuTankList = new List<string>();
                simuTankLevelList = new List<double>();
                simuTankStatusList = new List<int>();
                simuTankValvesList = new List<List<string>>();

                string msg = testMsg[testIndex];

                string resultStr = msg;
                int idx1 = resultStr.IndexOf("}#{");
                int idx2 = resultStr.LastIndexOf("}#{");
                if (idx1 >= 0 && idx2 >= 0 && idx1 != idx2)
                {
                    string tankStr = resultStr.Substring(idx1 + 3, idx2 - idx1 - 3);

                    string shipStr = resultStr.Substring(idx2 + 3);
                    string[] tankParts = tankStr.Split("#".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                    for (int i = 0; i < tankParts.Length; i += 12)
                    {
                        simuTankList.Add(tankParts[i]);
                        simuTankLevelList.Add(double.Parse(tankParts[i + 3]));
                        simuTankStatusList.Add(0);
                    }

                    if (simuTankList.Count() > 0 && simuTankList.Count() == simuTankLevelList.Count())
                    {
                        Dictionary<string, double> currentInnDic0 = oilBallast.GetTankInnDic();
                        for (int i = 0; i < simuTankList.Count(); i++)
                        {
                            string tankname = simuTankList[i];
                            double targetLevel = simuTankLevelList[i];

                            double currentlevel = currentInnDic0[tankname];
                            if (targetLevel > currentlevel)
                            {
                                simuTankStatusList[i] = 1;
                            }
                            else
                            {
                                simuTankStatusList[i] = -1;
                            }
                            string statusname = string.Empty;
                            if (tankname.IndexOf("CO") > -1)
                            {
                                if (simuTankStatusList[i] == 1)
                                {
                                    statusname = "注入";
                                }
                                else if (simuTankStatusList[i] == -1)
                                {
                                    statusname = "外输";
                                }
                            }
                            else if (tankname.IndexOf("WB") > -1)
                            {
                                if (simuTankStatusList[i] == 1)
                                {
                                    statusname = "压载";
                                }
                                else if (simuTankStatusList[i] == -1)
                                {
                                    statusname = "排载";
                                }
                            }

                            string searchname = string.Format("{0}_{1}", tankname, statusname);
                            //启动调载过程
                            foreach (OpcTask opcTask in taskList)
                            {
                                if (opcTask.TaskName == searchname)
                                {
                                    List<string> valveList = new List<string>();
                                    List<OPCTag> closeCheckTags = new List<OPCTag>();
                                    Dictionary<string, object> openComDic = new Dictionary<string, object>();
                                    foreach (OPCTag tag in opcTask.TagList)
                                    {
                                        string status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag.OpcName);

                                        //NOTICE 实船使用这部分
                                        if (tag.OpcName.Contains("SCM_Open"))
                                        {
                                            openComDic.Add(status_tag, 1);
                                            valveList.Add(tag.OpcName);
                                            continue;
                                        }
                                        else
                                            closeCheckTags.Add(tag);
                                    }
                                    simuTankValvesList.Add(valveList);
                                    //检查需关闭的设备是否按要求关闭，如有不符合要求的，则返回false
                                    try
                                    {
                                        opcUtil.GetOpcValues(closeCheckTags);
                                    }
                                    catch (Exception ex)
                                    {
                                        MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                                    }
                                    bool closeCheck = true;
                                    string closeCheckRes = "";
                                    foreach (OPCTag tag in closeCheckTags)
                                    {
                                        //DEBUG 这里需要确认下位机statusclosed的数据类型
                                        bool valStr = Convert.ToBoolean(tag.OpcValue.Value);
                                        if (valStr != true)
                                        {
                                            closeCheck = false;
                                        }
                                        closeCheckRes += string.Format("{0}:Value = {1}\n", tag.OpcName, tag.OpcValue.Value);
                                    }
                                    MessageBox.Show(closeCheckRes);
                                    //如果设备都按要求关闭，则可以下发开指令
                                    if (closeCheck)
                                    {
                                        try
                                        {
                                            opcUtil.SetOpcValues(openComDic);
                                        }
                                        catch (Exception ex)
                                        {
                                            MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                if (simuTankList.Count() > 0 && simuTankList.Count() == simuTankLevelList.Count())
                {
                    Dictionary<string, double> currentInnDic0 = oilBallast.GetTankInnDic();
                    for (int i = 0; i < simuTankList.Count(); i++)
                    {
                        string tankname = simuTankList[i];
                        double targetLevel = simuTankLevelList[i];
                        int status = simuTankStatusList[i];

                        double currentlevel = currentInnDic0[tankname];
                        if ((status == 1 && targetLevel <= currentlevel) || (status == -1 && targetLevel >= currentlevel))
                        {
                            //停止调载过程
                            string statusname = string.Empty;
                            if (tankname.IndexOf("CO") > -1)
                            {
                                if (simuTankStatusList[i] == 1)
                                {
                                    statusname = "注入";
                                }
                                else if (simuTankStatusList[i] == -1)
                                {
                                    statusname = "外输";
                                }
                            }
                            else if (tankname.IndexOf("WB") > -1)
                            {
                                if (simuTankStatusList[i] == 1)
                                {
                                    statusname = "压载";
                                }
                                else if (simuTankStatusList[i] == -1)
                                {
                                    statusname = "排载";
                                }
                            }

                            string searchname = string.Format("{0}_{1}", tankname, statusname);
                            simuTankStatusList[i] = 0;
                            foreach (OpcTask opcTask in taskList)
                            {
                                if (opcTask.TaskName == searchname)
                                {
                                    Dictionary<string, object> openComDic = new Dictionary<string, object>();
                                    foreach (OPCTag tag in opcTask.TagList)
                                    {
                                        string status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag.OpcName);

                                        //NOTICE 测试使用这部分
                                        if (tag.OpcName.Contains("SCM_Open"))
                                        {

                                            //这里要加上一段逻辑，如果当前需要停止的阀门，是其他正在装卸舱需要开启的阀门，则该阀门不停止
                                            bool opencheck = false;
                                            for (int m = 0; m < simuTankList.Count(); m++)
                                            {
                                                int ongoing = simuTankStatusList[m];
                                                if (ongoing != 0)
                                                {
                                                    List<string> valveList = simuTankValvesList[m];
                                                    foreach (string valvename in valveList)
                                                    {
                                                        if (tag.OpcName == valvename)
                                                        {
                                                            opencheck = true;
                                                            break;
                                                        }
                                                    }
                                                }
                                            }
                                            if (!opencheck)
                                            {
                                                openComDic.Add(status_tag, 0);
                                                string opcname0 = tag.OpcName.Replace("SCM_Open", "StatusOpened");
                                                status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, opcname0);
                                                openComDic.Add(status_tag, 0);
                                                string opcname1 = tag.OpcName.Replace("SCM_Open", "StatusClosed");
                                                status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, opcname1);
                                                openComDic.Add(status_tag, 1);
                                            }
                                        }
                                    }
                                    if (openComDic.Count > 0)
                                    {
                                        try
                                        {
                                            opcUtil.SetOpcValues(openComDic);
                                        }
                                        catch (Exception ex)
                                        {
                                            MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
